﻿(function(){
    function slider(params){
        var obj={
            el:params.el,
            w:params.w || 280, //canvas的宽度
            h:params.h || 150,  //canvas的高度
            range:params.range || 5, //相差多少像素内触发成功
            imgArr:params.imgArr || [], //图片数组
            sliderW:36, //slider的边长
            sliderIcon:params.sliderIcon || '',
            refresh:params.refresh, //刷新回调
            finish:params.finish , //完成回调
 
        };
 
           //创建canvas的父元素
           var container=document.querySelector(obj.el);
           container.innerHTML='';
           var canvas_wrap=document.createElement('div');
           canvas_wrap.className="canvas_wrap";
           canvas_wrap.style.cssText="position:relative;overflow:hidden;border-radius:4px;width:"+obj.w+"px;height:"+obj.h+"px;background:#fff"
       //创建大小canvas元素
           var bigCanvas=document.createElement('canvas');
           var smartCanvas=bigCanvas.cloneNode(true);
           bigCanvas.width=smartCanvas.width=obj.w;
           bigCanvas.height=smartCanvas.height=obj.h;
           bigCanvas.style.cssText=smartCanvas.style.cssText="position:absolute;left:0;top:0";
           var bcxt=bigCanvas.getContext('2d'),scxt=smartCanvas.getContext('2d'),img=new Image();
       //创建标题和刷新按钮
          var titleDom=document.createElement('div');
          var refreshDom=document.createElement('div');
          titleDom.className="slider_title";
          refreshDom.className="slider_refresh";
          titleDom.style.cssText="position:relative;width:"+obj.w+"+px;height:60px;text-align:center;font-size:18px; line-height:60px";
          refreshDom.style.cssText="position:absolute;top:0;right:14px;font-size:14px;color:green;cursor: pointer";
          titleDom.innerHTML="图形验证";
          refreshDom.innerHTML="刷新";
 
       //创建拖拽区域
         var slider_wrap=document.createElement('div'),slider=document.createElement('div'),sliderCover=document.createElement('div');
           slider_wrap.className="slider_wrap";
           slider.className="canvas_slider";
           sliderCover.className="sliderCover";
           slider_wrap.innerText="拖动左边滑块完成上方拼图";
           slider_wrap.style.cssText="width:"+obj.w+"px;height:30px; border-radius:30px;line-height:30px; position:relative;margin-top:10px;text-align:center;box-shadow: inset 0 0 4px #ccc;font-size: 14px;color:#999";
           slider.style.cssText="cursor: pointer;position: absolute;left: 0;top: 50%;z-index: 2;height: "+obj.sliderW+"px;width: "+obj.sliderW+"px;background:rgb(0, 124, 255) url("+obj.sliderIcon+") no-repeat center;background-size: 60% 60%;border-radius: "+obj.sliderW+"px;line-height:"+obj.sliderW+"px;text-align:center;transform: translateY(-50%);";
           sliderCover.style.cssText="position: absolute;left: 0;top:0;width:0;height:100%;background:#eee;border-radius:30px;"
          
           slider_wrap.appendChild(slider);
           slider_wrap.appendChild(sliderCover);
           canvas_wrap.appendChild(bigCanvas);
           canvas_wrap.appendChild(smartCanvas);
           titleDom.appendChild(refreshDom);
           container.appendChild(titleDom);
           container.appendChild(canvas_wrap);
           container.appendChild(slider_wrap);
       
        
        var canvasCoverL=0,startDownX=0,smartCanvasBL=0,sliderMaxRange=obj.w-obj.sliderW;  
        /*
        canvasCoverL:随机生成占位块canvas的x轴位置
        startDownX://鼠标按下时x轴位置
        smartCanvasBL: 可移动canvas的left初始值
        sliderMaxRange：slider可移动的最大距离
        */
 
        //生成canvas图案
        function creatCanvas(){
            //重置初始值
            canvasCoverL=0;startDownX=0;smartCanvasBL=0;  
            slider.style.left = sliderCover.style.width = 0;
 
            var l= 40, //滑块的正方形边长，不包括小圆点
            r = 10,   //小圆点半径
            PI = Math.PI,
            sliderW=l+2*r, //滑块边长
            rand=canvasSize(sliderW,r), //获取随机生成的x,y,left值
            x = canvasCoverL= rand.x,  //占位块x轴
            y = rand.y;  //占位块y轴
            
            smartCanvasBL=rand.left;
            //先清空画布
            bcxt.clearRect(0, 0, obj.w, obj.h)
            scxt.clearRect(0, 0, obj.w, obj.h)
            smartCanvas.width=obj.w;
 
            var srcIndex=Math.floor(Math.random()*(obj.imgArr.length-1));
            img.src=obj.imgArr[srcIndex];
            draw(scxt,x,y,l,r,PI,'clip');
            draw(bcxt,x,y,l,r,PI,'fill');
            img.onload = function() { //一定要在onload里调用，否则canvas里不能放进图片
                bcxt.drawImage(img,0,0,obj.w,obj.h);
                scxt.drawImage(img,0,0,obj.w,obj.h);
                //裁剪滑块长度
                var ImageData = scxt.getImageData(x, y-2*r, sliderW, sliderW)
                smartCanvas.width = sliderW;
                smartCanvas.style.left=rand.left+"px";
                scxt.putImageData(ImageData, 0, y-2*r)
            } 
            obj.refresh && obj.refresh();
        }
 
        //随机生成canvas滑块和占位块，到左边的距离和到顶部的距离
        function canvasSize(cw,r){
           // cw为占位块和的宽度，r为绘制圆点的半径
           var random =Math.random();
           var x=Math.floor(obj.w/2 + random*(obj.w/2 - cw)); //x为占位块x坐标位置，保证占位块始终在画布的右半区域
           var y=Math.floor(r*2+random*(obj.h - cw - r*2)); //y为占位块y坐标位置,（值至少为小圆半径的2倍才能完全显示，因为绘制的原点是小正方形的左上角）
           var left =Math.floor(random*(obj.w/2 - cw)); //canvas滑块的left值，这里的值范围保证它始终在画布的左半区域
           return {x:x,y:y,left:left}
        }
 
        //绘制canvas滑块和占位块
        function draw(ctx,x,y,l,r,PI,operation) {
            ctx.beginPath()
                ctx.moveTo(x, y)
                ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI)
                ctx.lineTo(x + l, y)
                ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI)
                ctx.lineTo(x + l, y + l)
                ctx.lineTo(x, y + l)
                ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true)
                ctx.lineTo(x, y)
                ctx.lineWidth = 1
                ctx.fillStyle = 'rgba(200, 200, 200, 1)'
                ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'
                ctx.stroke()
                ctx[operation]()
                ctx.globalCompositeOperation = 'destination-over'
          }
        
 
        
 
        //滑块被按下
        function moveStart(e){
            var ev = e || window.event;
            startDownX = ev.touches!=undefined?  ev.touches[0].clientX : ev.clientX; 
            // 解决开始滑动时文字被选中的bug
            document.onselectstart = function() { return false; }; 
        }
        //滑块移动
        function moveProcess(e){
            var ev = e || window.event,downX = (ev.touches!=undefined)?  ev.touches[0].clientX : (startDownX!=0? ev.clientX : 0),range=downX-startDownX;
          //console.log(downX)
            var sliderRange= range<=0? 0 : (range<sliderMaxRange ? range : sliderMaxRange);
            slider.style.left=sliderRange+"px";
            sliderCover.style.width=obj.sliderW/2 + sliderRange +"px";
            smartCanvas.style.left=smartCanvasBL+sliderRange+"px";
        }
 
        //停止滑动
        function moveEnd(e){
            document.ontouchmove = null;
            document.onmousemove = null;
            document.onselectstart = null;
            var ev = e || window.event;
            var smartCanvasL= parseInt(smartCanvas.style.left);
            if(Math.abs(canvasCoverL - smartCanvasL) < obj.range){
                obj.finish && obj.finish(true);
            }else{
                obj.finish && obj.finish(false);
                var timer = null,step = 10;
                var sliderL = parseInt(slider.style.left)
                timer = setInterval(function () {
                    sliderL -= step;
                    step += 5;
                    if (sliderL <= 0) {
                        clearInterval(timer);
                        sliderL = 0;
                        slider.style.left = sliderCover.style.width = 0;
                        smartCanvas.style.left = smartCanvasBL + "px"
                    }
                    slider.style.left =  sliderL + "px";
                    sliderCover.style.width = sliderL+obj.sliderW/2 +"px";
                    smartCanvas.style.left = sliderL + smartCanvasBL+ "px";
                }, 20)
            }
 
        }
        
        
       //事件调用
        creatCanvas();
        refreshDom.onclick=refreshDom.ontouchstart=creatCanvas;
        slider.ontouchstart=function(){
            moveStart();
            document.ontouchmove=moveProcess;
            document.ontouchend=moveEnd;
        };
        slider.onmousedown=function(){
            moveStart();
            document.onmousemove=moveProcess;
            document.onmouseup=moveEnd;
        };
       
    }
 
    window.$newSlider=slider
})()
